package pe.org.cnl.firma;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import org.bouncycastle.tsp.TimeStampToken;

import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PdfPKCS7;
import com.itextpdf.text.pdf.security.PrivateKeySignature;

public class TestPdf {

	private String pdfFirmado;
	
	public String getPdfFirmado() {
		return pdfFirmado;
	}

	public void setPdfFirmado(String pdfFirmado) {
		this.pdfFirmado = pdfFirmado;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TestPdf p = new TestPdf();
		System.out.println("===========INICIO============");
		p.firmarPDF();
		System.out.println("===========FIRMADO============");
		//p.verificaPdf( p.getPdfFirmado() );
		System.out.println("===========VERIFICADO 1============");
		p.agregaTexto( p.getPdfFirmado() );
		System.out.println("===========MODIFICADO============");
		//p.verificaPdf( p.getPdfFirmado() );
		System.out.println("===========VERIFICADO 2============");
		System.out.println("===========FIN============");
	//	p.firmarRTF();
	}

	/**
	 * Recibe un PDF y devuelve un nuevo PDF firmado
	 */
	public void firmarPDF(){
		System.out.println("recibo PDF y devuelvo un nuevo PDF firmado");
		try {
			
	//		File pdf = Utiles.obtieneYvalidaFile("resources/28066.pdf");
			
			KeyStore ks = KeyStore.getInstance("pkcs12");
			ks.load(new FileInputStream("resources/cherreracred.p12"), "cherrerap12".toCharArray());
			String alias = (String)ks.aliases().nextElement();
			PrivateKey key = (PrivateKey)ks.getKey(alias, "cherrerap12".toCharArray());
			Certificate[] chain = ks.getCertificateChain(alias);
			PdfReader reader = new PdfReader("resources/28066.pdf");
			this.pdfFirmado = "resources/28066_"+new Date().getTime()+".pdf";
			FileOutputStream fout = new FileOutputStream( this.pdfFirmado );
			
			PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');			
			PdfSignatureAppearance sap = stp.getSignatureAppearance();
			//sap.setCrypto(key, chain, null, PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
			sap.setReason("I'm the author");
			sap.setLocation("Lima - Peru");
			// comment next line to have an invisible signature
			sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
			
			sap.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
			
			ExternalSignature es = new PrivateKeySignature(key, DigestAlgorithms.SHA256 , null);
		    ExternalDigest digest = new BouncyCastleDigest();
		    MakeSignature.signDetached(sap, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);
		        
		    System.out.println("Fin de la firma. OK");
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void agregaTexto( String pdf ){
		try {
			PdfReader reader = new PdfReader( pdf );
			String nombre = pdf;
			nombre = nombre.substring(0, nombre.length()-4 );
			nombre = nombre + "_1.pdf";
			this.pdfFirmado = nombre;
			System.out.println( "nuevo nombre = " + nombre);
			PdfStamper stamper = new PdfStamper(reader, new FileOutputStream( nombre ));
			PdfContentByte canvas = stamper.getOverContent(1);
			ColumnText.showTextAligned(canvas,
			Element.ALIGN_LEFT, new Phrase("MODIFICADO POR ELVIS "), 36, 540, 0);
			stamper.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	public void verificaPdf( String pdf ){
		try {
			System.out.println("verifico integridad de pdf");
			Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
			KeyStore kall = KeyStore.getInstance("pkcs12");
			PdfReader reader = new PdfReader( pdf );
			AcroFields af = reader.getAcroFields();
			ArrayList names = af.getSignatureNames();
			for (int k = 0; k < names.size(); ++k) {
			    String name = (String)names.get(k);
			    System.out.println("Signature name: " + name);
			    System.out.println("Signature covers whole document: " + af.signatureCoversWholeDocument(name));
			    System.out.println("Document revision: " + af.getRevision(name) + " of " + af.getTotalRevisions());
			    // Start revision extraction
			    FileOutputStream out = new FileOutputStream("resources/revision_" + af.getRevision(name) + ".pdf");
			    byte bb[] = new byte[8192];
			    InputStream ip = af.extractRevision(name);
			    int n = 0;
			    while ((n = ip.read(bb)) > 0)
			        out.write(bb, 0, n);
			    out.close();
			    ip.close();
			    // End revision extraction
			    PdfPKCS7 pk = af.verifySignature(name);
			    Calendar cal = pk.getSignDate();
			    X509Certificate pkc[] = (X509Certificate[])pk.getSignCertificateChain();
			    TimeStampToken ts = pk.getTimeStampToken();
			    if (ts != null)
			        cal = pk.getTimeStampDate();
			    if (!pk.isTsp() && ts != null) {
			        boolean impr = pk.verifyTimestampImprint();
			        System.out.println("Timestamp imprint verifies: " + impr);
			        System.out.println("Timestamp date: " + cal);
			    }
			    
			  //  System.out.println("Subject: " + PdfPKCS7.getSubjectFields( pk.getSigningCertificate() ));
			    System.out.println("Document modified: " + !pk.verify());
			  //  Object fails[] = PdfPKCS7.verifyCertificates(pkc, kall, null, cal);
			//    if (fails == null)
			 //       System.out.println("Certificates verified against the KeyStore");
			 //   else
			//        System.out.println("Certificate failed: " + fails[1]);
			    
			 /*   BasicOCSPResp ocsp = pk.getOcsp();
			    if (ocsp != null) {
			        InputStream inStream = new FileInputStream("C:/responder.cer");
			        CertificateFactory cf = CertificateFactory.getInstance("X.509");
			        X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
			        inStream.close();
			        System.out.println("OCSP signature verifies: " + ocsp.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider("BC").build(cert.getPublicKey())));
			        System.out.println("OCSP revocation refers to this certificate: " + pk.isRevocationValid());
			    }*/
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	/**
	 * Recibe un RTF y devuelve un PDF firmado
	 */
	public void firmarRTF(){
		System.out.println("recibo RTF y devuelvo un PDF firmado");
	}
}

